import datetime
import secrets
from flask import Blueprint, request
from flask import session
import hashlib
from common.exceptions import IdentificationFailed, NotFoundException, TooManyRequestException, ParameterException, \
    ExpireException
from model.article import ArticleModel
from model.book import BookSpaceModel
from model.email_model import EmailService
from model.team import TeamSpaceModel
from model.user import UserModal
from util.args_validate import ArgsValidate
from util.db import Cursor, RedisCursor
from flask_restx import reqparse

from util.login_validate import login_validate

app_auth = Blueprint(name="app_auth", import_name=__name__, url_prefix='/api/user')


class Register:

    @staticmethod
    @app_auth.route('/register', methods=['POST'])
    def post_register():
        parser = reqparse.RequestParser()
        parser.add_argument('email', type=str, help='邮箱', trim=True)
        parser.add_argument('phone', type=str, help='电话', trim=True)
        parser.add_argument('code', type=str, required=True, help='邮箱验证码', trim=True)
        parser.add_argument('username', type=ArgsValidate.username_validate, required=True, help='用户名', trim=True)
        parser.add_argument('password', type=ArgsValidate.username_validate, required=True, help='用户密码', trim=True)
        args = parser.parse_args(strict=True)
        user_email = args.get('email')
        user_phone = args.get('phone')
        username = args.get('username')
        code = args.get('code')
        remote_addr = request.remote_addr

        with RedisCursor() as r:
            key = ':'.join([user_email, remote_addr])
            if not r.get(key) or r.get(key).decode() != code:
                raise ExpireException('验证码已过期或不正确，请重新获取')
        password = hashlib.sha256(args.get('password').encode()).hexdigest()
        create_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        with Cursor() as cursor:
            sql = """select `id` from `yugong_user` where `username`=%s for update"""
            cursor.execute(sql, [username])
            res = cursor.fetchall()
            if res:
                return {"code": 1, "errMsg": "用户名/邮箱/手机号已注册", "data": []}, 200
            else:
                role = 1
                sql = """insert into yugong_user (`username`, `password`, 
                `email`, `phone`, `create_time`, `role`) values (%s, %s, %s, %s, %s, %s)"""
                cursor.execute(sql, [username, password, user_email, user_phone, create_time, role])
        return {"code": 0, "errMsg": "注册成功", "data": []}, 200


class Login:

    @staticmethod
    @app_auth.route('/login', methods=['POST'])
    def post_login():
        parser = reqparse.RequestParser()
        parser.add_argument('username', type=ArgsValidate.username_validate, required=True, help='用户名', trim=True)
        parser.add_argument('password', type=ArgsValidate.username_validate, required=True, help='用户密码', trim=True)
        args = parser.parse_args(strict=True)
        username = args.get('username')
        password = hashlib.sha256(args.get('password').encode()).hexdigest()
        user_id = None
        with Cursor() as cursor:
            sql = """select `id`, `role`, `username` from `yugong_user` where `username`=%s or email=%s"""
            cursor.execute(sql, [username, username])
            res = cursor.fetchall()
            if not res:
                return {"code": 1, "errMsg": "您的账户未注册，请注册后登陆", "data": []}, 200
            else:
                sql = """select `id`, `role`, `username`, `email` from `yugong_user` where (`username`=%s or email=%s) and `password`=%s"""
                cursor.execute(sql, [username, username, password])
                res = cursor.fetchall()
                if res:
                    user_id = res[0].get('id')
                else:
                    raise IdentificationFailed(msg='认证失败，账户或密码错误')
        username = res[0].get('username')
        csrf_token = secrets.token_hex(24)
        session['x-csrf-token'] = csrf_token
        session['role'] = res[0].get('role')
        session['username'] = username
        session['login_status'] = True
        session['user_id'] = user_id
        return {"code": 0, "errMsg": "登录成功", "data": {'token': csrf_token}}, 200


class ForgetPassword:

    @staticmethod
    @app_auth.route('/forgetPassword', methods=['POST'])
    def post_forget_password():
        parser = reqparse.RequestParser()
        parser.add_argument('email', type=ArgsValidate.username_validate, required=True, help='邮箱', trim=True)
        parser.add_argument('password', type=ArgsValidate.username_validate, required=True, help='用户密码', trim=True)
        parser.add_argument('code', type=ArgsValidate.code_validate, required=True, help='验证码', trim=True)

        args = parser.parse_args(strict=True)
        remote_addr = request.remote_addr
        password = hashlib.sha256(args.get('password').encode()).hexdigest()
        email = args.get('email')
        code = args.get('code')

        with RedisCursor() as r:
            key = ':'.join([email, remote_addr])
            if not r.get(key) or r.get(key).decode() != code:
                raise ExpireException('验证码已过期或不正确，请重新获取')

        with Cursor() as cursor:
            sql = """select `id` from `yugong_user` where `email`=%s for update"""
            cursor.execute(sql, [email])
            res = cursor.fetchall()
            if not res:
                return {"code": 1, "errMsg": "您的邮箱尚未注册", "data": []}, 200
            else:
                id = res[0].get('id')
                sql = """update yugong_user set password=%s where `id`=%s"""
                cursor.execute(sql, [password, id])
        return {"code": 0, "errMsg": "密码修改成功", "data": []}, 200


class UserInfo:
    """用户基本信息相关"""

    @staticmethod
    @app_auth.route('/userInfo', methods=['PATCH'])
    @login_validate
    def patch_user_info():
        parser = reqparse.RequestParser()
        parser.add_argument('department', type=str, help='部门', trim=True)
        parser.add_argument('job', type=str, help='职位', trim=True)
        parser.add_argument('email', type=str, help='邮箱', trim=True)
        parser.add_argument('phone', type=str, help='手机号', trim=True)
        parser.add_argument('status', type=str, help='状态', trim=True)
        parser.add_argument('address', type=str, help='地址', trim=True)
        parser.add_argument('description', type=str, help='个人简介', trim=True)
        parser.add_argument('username', type=str, help='用户名', trim=True)

        args = parser.parse_args(strict=True)
        user_id = session.get('user_id')
        department = args.get('department')
        job = args.get('job')
        email = args.get('email')
        phone = args.get('phone')
        status = args.get('status')
        address = args.get('address')
        description = args.get('description')
        username = args.get('username')

        with Cursor() as cursor:
            sql = """update `yugong_user` set department=%s, job=%s, email=%s, phone=%s, status=%s, address=%s, description=%s, username=%s where `id`=%s"""
            cursor.execute(sql, [department, job, email, phone, status, address, description, username, user_id])
        user_info = UserModal.get_user_info()
        return {"code": 0, "errMsg": "更新成功", "data": user_info}, 200

    @staticmethod
    @app_auth.route('/userAvatar', methods=['PATCH'])
    @login_validate
    def patch_user_avatar():
        user_id = session.get('user_id')
        parser = reqparse.RequestParser()
        parser.add_argument('avatar', type=str, help='用户头像', trim=True)
        args = parser.parse_args(strict=True)
        avatar = args.get('avatar')
        with Cursor() as cursor:
            sql = """update `yugong_user` set avatar=%s where `id`=%s"""
            cursor.execute(sql, [avatar, user_id])
        user_info = UserModal.get_user_info()
        return {"code": 0, "errMsg": "更新成功", "data": user_info}, 200

    @staticmethod
    @app_auth.route('/userInfo', methods=['GET'])
    @login_validate
    def get_user_info():
        user_info = UserModal.get_user_info()
        return {"code": 0, "errMsg": "success", "data": user_info}, 200

    @staticmethod
    @app_auth.route('/verifyCode', methods=['POST'])
    def post_email_verify_code():
        """生成邮箱验证码"""
        parser = reqparse.RequestParser()
        parser.add_argument('email', type=str, help='邮箱', trim=True, required=True)
        args = parser.parse_args(strict=True)
        email = args.get('email')
        if not email:
            raise ParameterException('邮箱不能为空或邮箱格式不合法')
        remote_addr = request.remote_addr
        code = EmailService.send_email_code(email)
        with RedisCursor() as r:
            key = ':'.join([email, remote_addr])
            if r.get(key):
                raise TooManyRequestException()
            r.setex(name=key, value=code, time=60)
        return {"code": 0, "errMsg": "验证码发送成功", "data": None}, 200


class UserSummary:
    """用户写作数据的大概统计"""

    @staticmethod
    @app_auth.route('/data', methods=['GET'])
    @login_validate
    def get_summary():
        parser = reqparse.RequestParser()
        parser.add_argument('flag', type=str, help='统计类型，知识库 | 团队', trim=True)
        args = parser.parse_args(strict=True)
        user_id = session.get('user_id')
        flag = args.get('flag')

        result = {}

        if flag == 'team':
            with Cursor() as cursor:
                result = {
                    'join': 0,
                    'total': 0,
                    'create': 0,
                    'data': []
                }
                sql = """select count(*) as total, cast(sum(`created`) as SIGNED) as `create`, cast(sum(`joind`) as SIGNED) as `join`
                from yugong_role_team where user_id=%s"""
                cursor.execute(sql, [user_id])
                summary = cursor.fetchall()
                if summary:
                    result.update(summary[0])
                data = TeamSpaceModel.get_user_team_space()
            result['data'] = data
            return {"code": 0, "errMsg": "成功", "data": result}, 200

        if flag == 'book':
            with Cursor() as cursor:
                result = {
                    'join': 0,
                    'total': 0,
                    'create': 0,
                    'data': []
                }
                sql = """select count(*) as `create` from yugong_book where user_id=%s"""
                cursor.execute(sql, [user_id])
                create = cursor.fetchall()
                if create:
                    result['create'] = create[0]['create']
                sql = """select count(*) as `join` from yugong_book where team_id in (select team_id from yugong_role_team where user_id=%s and joind=1) and user_id !=%s  and auth != 1"""
                cursor.execute(sql, [user_id, user_id])
                join = cursor.fetchall()
                if join:
                    result['join'] = join[0]['join']
                result['total'] = result['join'] + result['create']
                data = BookSpaceModel.get_user_book_space()
            result['data'] = data
            return {"code": 0, "errMsg": "成功", "data": result}, 200

        if flag == 'article':
            result = {
                'join': 0,
                'total': 0,
                'create': 0,
                'data': []
            }
            with Cursor() as cursor:
                sql = """select count(*) as `create` from yugong_article where create_person=%s"""
                cursor.execute(sql, [user_id])
                create = cursor.fetchall()
                if create:
                    result['create'] = create[0]['create']
                sql = """select count(*) as `join` from yugong_article where team_id in (select team_id from yugong_role_team where user_id=%s and joind=1) and create_person !=%s  and auth != 1"""
                cursor.execute(sql, [user_id, user_id])
                join = cursor.fetchall()
                if join:
                    result['join'] = join[0]['join']
                result['total'] = result['join'] + result['create']
                sql = """select * from yugong_article where create_person=%s
                        union all
                        select * from yugong_article where team_id in (select team_id from yugong_role_team where user_id=%s and joind=1) and create_person !=%s  and auth != 1
                """
                cursor.execute(sql, [user_id, user_id, user_id])
                data = cursor.fetchall()
                result['data'] = data
            return {"code": 0, "errMsg": "成功", "data": result}, 200
        return {"code": 0, "errMsg": "成功", "data": result}, 200

class Logout:

    @staticmethod
    @app_auth.route('/logout', methods=['POST'])
    @login_validate
    def post_logout():
        session.clear()
        return {"code": 0, "errMsg": "注销成功", "data": []}, 200


class LoginStatus:
    @staticmethod
    @app_auth.route('/loginStatus', methods=['GET'])
    def get_login_status():
        login_status = session.get('login_status', False)
        return {"code": 0, "errMsg": "登录状态查询成功", "data": {'loginStatus': login_status}}, 200


class UserPersonal:
    """用户对外公开的个人主页信息，不需要登录即可访问"""

    @staticmethod
    @app_auth.route('/personal_data', methods=['GET'])
    def get_personal_summary():
        parser = reqparse.RequestParser()
        parser.add_argument('userId', type=int, help='用户ID', trim=True)
        parser.add_argument('flag', type=str, help='用户ID', trim=True)
        args = parser.parse_args(strict=True)
        user_id = args.get('userId')
        flag = args.get('flag')

        result = {'total': 0, 'data': []}
        data = []
        if flag == 'book':
            data = BookSpaceModel.get_book_space_without_login(user_id)
        result['total'] = len(data)
        result['data'] = data
        return {"code": 0, "errMsg": "成功", "data": result}, 200

    @staticmethod
    @app_auth.route('/personal_basic', methods=['GET'])
    def get_personal_basic_info():
        parser = reqparse.RequestParser()
        parser.add_argument('userId', type=int, help='用户ID', trim=True)
        args = parser.parse_args(strict=True)
        user_id = args.get('userId')
        with Cursor() as cursor:
            sql = """select * from `yugong_user` where `id`=%s"""
            cursor.execute(sql, [user_id])
            res = cursor.fetchall()[0]
            if not res:
                raise NotFoundException('用户不存在')
            user_info = {
                "avatar": res.get('avatar'),
                "id": user_id,
                "username": res.get('username'),
                "job": res.get('job'),
                "address": res.get('address'),
                "email": res.get('email'),
                "description": res.get('description')
            }
        return {"code": 0, "errMsg": "success", "data": user_info}, 200